﻿using System;
using System.Data.Common;
using System.Linq;

namespace Centido.Management.ConsoleManager
{
    /// <summary>
    ///   A console command that adds the specified business unit into another business unit.
    /// </summary>
    internal class AddUnitInUnitCommand : Command
    {
        /// <summary>
        ///   The unit name parameter.
        /// </summary>
        public const string UnitNameParameter = "unit";

        /// <summary>
        ///   The unit name parameter (short name).
        /// </summary>
        public const string UnitNameShortParameter = "u";

        /// <summary>
        ///   The parent unit name.
        /// </summary>
        public const string ParentUnitNameParameter = "parentunit";

        /// <summary>
        ///   The parent unit name (short name).
        /// </summary>
        public const string ParentUnitNameShortParameter = "pu";


        /// <summary>
        ///   Gets the console command name.
        /// </summary>
        public override string Name
        {
            get { return "addunitinunit"; }
        }


        /// <summary>
        ///   Gets the console command description.
        /// </summary>
        public override string Description
        {
            get { return Messages.AddUnitInUnitCommandDescription; }
        }


        /// <summary>
        ///   Gets the console command full description.
        /// </summary>
        public override string FullDescription
        {
            get { return Messages.AddUnitInUnitCommandFullDescription; }
        }


        /// <summary>
        ///   Executes the console command.
        /// </summary>
        /// <param name="context">The console command execution context.</param>
        /// <exception cref="ArgumentNullException">Thrown when the value of <paramref name="context"/> is null.</exception>
        public override void Execute(CommandExecutionContext context)
        {
            base.Execute(context);

            // If the unit name or the parent unit name was not specified
            if (!context.ParameterValueIsNotEmpty(UnitNameParameter, UnitNameShortParameter)
                || !context.ParameterValueIsNotEmpty(ParentUnitNameParameter, ParentUnitNameShortParameter))
            {
                Console.WriteLine(Messages.AddUnitInUnitCommandNotAllParametersSpecifiedError);
                return;
            }

            var domain = context.CurrentDomain;

            if (domain == null) return;

            // If the current user has no permission to perform this operation
            if (!domain.CurrentUser.CanChangeSecurity)
            {
                Console.WriteLine(Messages.NeedCanChangeSecurityPermissionMessage);
                return;
            }

            // The unit name
            var unitName = context.GetParameterValue(UnitNameParameter, UnitNameShortParameter);

            // The parent unit name
            var parentUnitName = context.GetParameterValue(ParentUnitNameParameter, ParentUnitNameShortParameter);

            try
            {
                // Trying to find the unit
                var unit = domain.GetUnit(unitName);

                // If the unit with the sepcified name was not found
                if (unit == null)
                {
                    Console.WriteLine(Messages.CannotFindUnitError, unitName);
                    return;
                }

                // Trying to find the parent unit
                var parentUnit = domain.GetUnit(parentUnitName);

                if (parentUnit == null)
                {
                    Console.WriteLine(Messages.CannotFindUnitError, parentUnitName);
                    return;
                }

                if (!unit.Parents.Any(p => p.Id == parentUnit.Id))
                    parentUnit.AddUnit(unit);
            }
            catch (DbException e)
            {
                Console.WriteLine(e.Message);
                Console.WriteLine();
                return;
            }

            // Displaying the success message
            Console.WriteLine(Messages.CommandCompletedMessage);
        }
    }
}
